﻿//------------------------------------------------------------------------------
// System Name:   Customer Service Platform
// Component:     All Aera
// Created By:    Miles Chen (milesch@wicresoft.com)
// Created Date:  2011-2-9
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ASBCC.Business
{
    /// <summary>
    /// Base class for entity bound page
    /// </summary>
    public abstract class EntityPage : Page
    {
        protected enum EntityMode
        {
            Grid,
            Detail
        }

        protected abstract EntityDataSource EntitySource { get; }
        protected abstract GridView EntityGrid { get; }
        protected abstract DetailsView EntityDetails { get; }
        protected abstract TextBox EntitySearchTxt { get; }
        protected abstract Button EntityAddBtn { get; }
        protected abstract Button EntityClearBtn { get; }
        //TODO: make it abstract when all the inheritances are updated
        protected virtual Button EntitySearchBtn { get { return null; } }
        protected virtual Panel GridPanel { get { return null; } }

        protected abstract void OnEntityDisabling(int entityKey);
        protected abstract void OnEntityInserting(EntityDataSourceChangingEventArgs e);
        protected abstract void OnEntityUpdating(EntityDataSourceChangingEventArgs e);
        protected abstract string GetEntityWhereExpression(string keyword);
        protected virtual void OnEntityAuthorize(EntityMode mode, IEnumerable<DataControlField> fields) { }

        public int TotalRowCount
        {
            get
            {
                object obj2 = base.ViewState["EntityTotalRowCount"];
                return ((obj2 != null) ? ((int)obj2) : -1);
            }
            set
            {
                object obj2 = base.ViewState["EntityTotalRowCount"];
                if ((obj2 == null) || (((int)obj2) != value))
                {
                    base.ViewState["EntityTotalRowCount"] = value;
                }
            }
        }
        protected EntityMode CurrentMode;
        public int EntityIndex
        {
            get
            {
                object obj2 = base.ViewState["EntityIndex"];
                return ((obj2 != null) ? ((int)obj2) : -1);
            }
            set
            {
                object obj2 = base.ViewState["EntityIndex"];
                if ((obj2 == null) || (((int)obj2) != value))
                {
                    base.ViewState["EntityIndex"] = value;
                }
            }
        }


        protected CSPrincipal LogonUser
        {
            get
            {
                return (User as CSPrincipal);
            }
        }

        public bool ReadOnly
        {
            get
            {
                return LogonUser.AccessLevel == AccessLevel.Read;
            }
        }

        private static readonly string[] SortDirections = new string[] { "asc", "desc" };

        /// <summary>
        /// This method returns a collection which TemplateControls.Eval cannot
        /// </summary>
        protected object EvalX(string expression)
        {
            CheckPageExists();

            var ctd = base.Page.GetDataItem() as ICustomTypeDescriptor;
            if (ctd != null)
            {
                return DataBinder.Eval(ctd.GetPropertyOwner(null), expression);
            }
            else
                return null;
        }

        public object GetDataItemX()
        {
            CheckPageExists();

            var ctd = base.Page.GetDataItem() as ICustomTypeDescriptor;
            if (ctd != null)
            {
                return ctd.GetPropertyOwner(null);
            }
            else
                return base.Page.GetDataItem();
        }

        private void CheckPageExists()
        {
            if (base.Page == null)
            {
                throw new InvalidOperationException("TemplateControl_DataBindingRequiresPage");
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            EntitySource.Inserting += EntitySource_Inserting;
            EntitySource.Updating += EntitySource_Updating;
            EntitySource.Inserted += Entity_Changed;
            EntitySource.Updated += Entity_Changed;
            EntityAddBtn.Click += BtnAdd_Click;
            EntitySearchBtn.Click += EntitySearchBtn_Click;
            EntityClearBtn.Click += BtnClear_Click;
            EntityGrid.RowCommand += EntityGrid_RowCommand;
            EntityDetails.ItemCommand += EntityDetails_ItemCommand;
            EntitySource.Selected += EntitySource_Selected;

            EntityGrid.EmptyDataText = "There is no data according to the current search criteria<br />查无数据";
        }

        private void EntitySource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
        {
            // get GridView: Total Records
            // http://bytes.com/topic/asp-net/answers/474887-gridview-total-records
            // 当EntityDataSource从ViewState加载时，e.TotalRowCount永远为-1，所以过滤掉
            if (e.TotalRowCount != -1)
                TotalRowCount = e.TotalRowCount;
        }

        private void EntitySearchBtn_Click(object sender, EventArgs e)
        {
            // 当所搜开始，自动转到第一页！
            EntityGrid.PageIndex = 0;
        }


        private void EntityDetails_ItemCommand(object sender, DetailsViewCommandEventArgs e)
        {
            if (e.CommandName == "Cancel")
            {
                CurrentMode = EntityMode.Grid;
            }
            else if (e.CommandName == "New")
            {
                CurrentMode = EntityMode.Detail;
            }
            else if (e.CommandName == "Edit")
            {
                EntityGrid.SelectedIndex = EntityIndex;
                CurrentMode = EntityMode.Detail;
            }
        }

        protected override void OnLoadComplete(EventArgs e)
        {
            base.OnLoadComplete(e);

            BindWhereClause();
            BindOrderByClause();


            if (this.Request.Form["insert$more"] != null)
            {
                CurrentMode = EntityMode.Detail;
                EntityDetails.ChangeMode(DetailsViewMode.Insert);
                EntityDetails.FooterText = "<div class='entity-footer'>Operation succeeded, you can continue another action!<br />保存成功，您可以继续添加新的数据！</div>";
            }
            else
            {
                EntityDetails.FooterText = null;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            switch (CurrentMode)
            {
                case EntityMode.Grid:
                    EntityGrid.Visible = true;
                    EntityAddBtn.Visible = !ReadOnly;
                    EntitySearchTxt.Visible = true;
                    EntitySearchBtn.Visible = true;
                    EntityClearBtn.Visible = true;
                    if (GridPanel != null)
                        GridPanel.Visible = true;

                    EntityDetails.Visible = false;

                    OnEntityAuthorize(EntityMode.Grid, EntityGrid.Columns.Cast<DataControlField>().
                        Where(p => !(p is CommandField)));
                    break;
                case EntityMode.Detail:
                    EntityGrid.Visible = false;
                    EntityAddBtn.Visible = false;
                    EntitySearchTxt.Visible = false;
                    EntitySearchBtn.Visible = false;
                    EntityClearBtn.Visible = false;
                    if (GridPanel != null)
                        GridPanel.Visible = false;

                    EntityDetails.Visible = true;
                    if (EntityDetails.CurrentMode != DetailsViewMode.Insert)
                    {
                        EntityDetails.PageIndex = EntityIndex;
                        EntityDetails.DataBind();
                    }

                    OnEntityAuthorize(EntityMode.Detail, EntityDetails.Fields.Cast<DataControlField>().
                        Where(p => !(p is CommandField)));
                    break;
            }
        }

        private void BindActionFieldToTop()
        {
            var actionField = EntityDetails.Fields.Cast<DataControlField>().Last();
            EntityDetails.Fields.Insert(0, actionField);
        }

        protected void BtnAdd_Click(object sender, EventArgs e)
        {
            EntityDetails.ChangeMode(DetailsViewMode.Insert);
            CurrentMode = EntityMode.Detail;
        }

        private void EntityGrid_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            if (e.CommandName == "View")
            {
                SwitchToDetailsView(DetailsViewMode.ReadOnly, e.CommandArgument as string);
            }
            else if (e.CommandName == "Modify")
            {
                SwitchToDetailsView(DetailsViewMode.Edit, e.CommandArgument as string);
            }
            else if (e.CommandName == "Disable")
            {
                var selectedIndex = int.Parse(e.CommandArgument as string);
                var entityKey = (int)EntityGrid.DataKeys[selectedIndex].Value;

                OnEntityDisabling(entityKey);

                // 如果当前页只有一条数据并且页数大于0，则显示前一页
                if (EntityGrid.Rows.Count == 1 && EntityGrid.PageIndex > 0)
                    EntityGrid.PageIndex--;
                Entity_Changed(null, null);
            }
        }

        private void SwitchToDetailsView(DetailsViewMode mode, string argument)
        {
            EntityIndex = int.Parse(argument) +
                   EntityGrid.PageIndex * EntityGrid.PageSize;
            EntityGrid.SelectedIndex = int.Parse(argument);

            EntityDetails.ChangeMode(mode);
            CurrentMode = EntityMode.Detail;
        }

        private void BtnClear_Click(object sender, EventArgs e)
        {
            EntitySearchTxt.Text = null;
            Entity_Changed(null, null);
        }


        private void BindWhereClause()
        {
            if (EntitySearchTxt.Text == "Type keyword to search")
                EntitySearchTxt.Text = "";

            var additionalCondition = GetEntityWhereExpression(PageSafeHelper.SafeText(EntitySearchTxt.Text));

            if (!String.IsNullOrEmpty(EntitySource.Where) && !String.IsNullOrEmpty(additionalCondition))
                EntitySource.Where += " and (" + additionalCondition + ")";
            else if (!String.IsNullOrEmpty(EntitySource.Where) && String.IsNullOrEmpty(additionalCondition))
                EntitySource.Where = additionalCondition;
         

        }

        private void EntitySource_Updating(object sender, EntityDataSourceChangingEventArgs e)
        {
            OnEntityUpdating(e);
        }

        private void EntitySource_Inserting(object sender, EntityDataSourceChangingEventArgs e)
        {
            OnEntityInserting(e);
        }

        private void BindOrderByClause()
        {
            if (!String.IsNullOrEmpty(EntityGrid.SortExpression))
                EntitySource.OrderBy = "it." + EntityGrid.SortExpression + " "
                    + SortDirections[(int)EntityGrid.SortDirection];
        }

        protected void Entity_Changed(object sender, EntityDataSourceChangedEventArgs e)
        {
            BindWhereClause();
            BindOrderByClause();

            CurrentMode = EntityMode.Grid;
            EntityGrid.DataBind();
        }

    }
}
